<template>
  <div class="container">
    <div class="left-panel">
      <el-tree
        :data="dataTree"
        :props="defaultProps"
        default-expand-all
        :render-content="renderContent" />
    </div>
    <div class="right-panel">
      <div class="decision-tree-name panel">
        <!-- 决策树名称 -->
        <label for="decisionTreeName">决策模型名称：</label>
        <el-input
          v-model="decisionTreeId"
          placeholder="决策模型名称"
          @input="() => validateTreeInput('decisionTreeId')"
          class="decisionTree-text">
        </el-input>
      </div>
      <div class="data-list panel">
        <!-- 数据集列表 -->
        <label for="data-list panel">数据集列表：</label>
        <ul>
          <li
            v-for="item in datasetList"
            :key="item.name"
            @click="selectDataset(item)"
            :class="{ 'list-item': true, selected: item === selectedDataset }">
            {{ item.num }} - {{ item.name }}
          </li>
        </ul>
      </div>
      <div class="num-hosts-input panel">
        <el-input
          v-model="numHosts"
          placeholder="输入主机数量"
          @input="() => validateInput('numHosts')"
          class="input-command">
          <template v-slot:prepend>主机数量：</template>
        </el-input>
      </div>
      <div class="command-input panel">
        <!-- 动态生成主机数量的输入框 -->
        <div v-for="item in handleNumHosts" :key="item">
          <el-input
            v-model="params[item]"
            :placeholder="'主机' + item + 'ip,如localhost等'"
            @blur="() => validateIPInput(params[item], item)"
            class="input-command">
            <template v-slot:prepend>主机{{ item }}的ip地址</template>
          </el-input>
        </div>
        <el-input
          v-model="compoundCommand"
          placeholder="填写数字1-N"
          @input="() => validateInput('compoundCommand')"
          class="input-command">
          <template v-slot:prepend>本机是第几训练节点</template>
        </el-input>
      </div>
      <div class="actions panel">
        <!-- 删除和生成按钮 -->
        <button @click="deleteDecisionTree" class="btn-delete">删除</button>
        <button @click="generateDecisionTree" class="btn-generate">生成</button>
        <button @click="applicationDecisionTree" class="btn-application">
          应用
        </button>
      </div>
    </div>
  </div>
</template>

<script>

export default {
  data() {
    return {
      datasetList: [], // 数据集列表
      selectedDataset: null, // 选中的数据集
      decisionTreeId: '', // 决策树 ID
      params: [], // 用一个对象来存储动态生成的主机IP参数
      command:'',
      compoundCommand: '', // 复合指令
      numHosts: 3, // 默认主机数量为3
      // 树组件格式
      defaultProps: {
        children: 'children',
        label: 'condition',
      },
      // 树组件数据
      dataTree: [],
    }
  },
  computed: {
    handleNumHosts() {
      if (this.numHosts !== '') {
        return Number(this.numHosts)
      } else {
        return []
      }
    },
  },
  methods: {
    validateInput(modelName) {
    const regex = /^\d*$/; // 正则表达式匹配仅数字
    if (!regex.test(this[modelName])) {
      this.$message.error('请输入数字');
      this[modelName] = this[modelName].replace(/[^\d]/g, ''); // 移除非数字字符
    }
  },
  validateTreeInput(modelName) {
  // 正则表达式匹配任何非法字符 \?%#&$=
  const regex = /[\\?%#&$=]+/g;
  if (regex.test(this[modelName])) {
    this.$message.error('非法字符');
    this[modelName] = this[modelName].replace(regex, '');
  }
  console.log("决策树模型" + this.decisionTreeId)
},
  validateIPInput(value, key) {
    // 正则表达式匹配 IPv4 地址或 "localhost"
    const regex = /^(localhost|((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?))$/;
    if (!regex.test(value)) {
      this.$message.error('请输入有效的 IP 地址或 localhost');
      this.params[key] = ''
    }
    
  },

    generateCommand() {
      console.log(this.params)
      let isLegal = true;
      for(let i=1;i<=this.numHosts; i++){
        if(this.params[i] === undefined || this.params[i] === '') {
          this.$message.error(`请输入主机${i}的ip地址!`);
          isLegal = false;
          break
        }
      }
      if(this.compoundCommand =='') {
        this.$message.error(`请指定本机的训练节点`);
        isLegal = false;
      }
      for (let i = 1; i <= this.numHosts; i++) {
        this.command += `-P ${this.params[i]} `
      }
      if (this.compoundCommand && !isNaN(this.compoundCommand)) {
        this.command += `-I ${this.compoundCommand - 1}`
      }
      return isLegal
    },

    // 解析决策树文本
    parseDecisionTreeToJSON(treeText) {
      const lines = treeText.split('\n').slice(1)
      const root = { children: [] }
      const stack = [{ node: root, level: -1 }]

      lines.forEach((line) => {
        const level = (line.match(/\|/g) || []).length
        let content = line.replace(/\|/g, '').trim()

        const node = {
          condition: '',
          result: '',
        }

        if (content.includes(':')) {
          let [condition, result] = content.split(':')
          condition = condition.replace('if ', '').trim()
          node.condition = condition
          node.result = result.trim()
          if (node.result != '') {
            node.condition = `${condition} -> ${result.trim()}`
          }
        } else {
          node.condition = content.replace('if ', '')
        }

        while (stack.length > 0 && stack[stack.length - 1].level >= level) {
          stack.pop()
        }

        const parentNode = stack[stack.length - 1].node
        if (!parentNode.children) {
          parentNode.children = []
        }
        parentNode.children.push(node)

        if (content.includes(':')) {
          stack.push({ node, level })
        }
      })

      function cleanupNodes(node) {
        if (node.children) {
          node.children.forEach((child) => cleanupNodes(child))
          if (node.children.length === 0) {
            delete node.children
          }
        }
      }

      root.children.forEach((child) => cleanupNodes(child))

      return root.children
    },
    // 获取树组件数据
    async getTreeData(treeId) {
      console.log('getTreeData' + treeId)
      await this.$axios
        .get('http://localhost/api/tree/treeDetail?treeId=' + treeId, {
          headers: {
            token: sessionStorage.getItem('token'),
          },
        })
        .then((res) => {
          if (res.data.code == 200) {
            this.$message.success('决策模型生成成功')
            let data = this.parseDecisionTreeToJSON(res.data.data)
            this.dataTree = data
          } else {
            this.$message.error('决策模型生成失败:' + res.data.msg)
          }
        })
        .catch((error) => {
          console.log(error)
          this.$message.error('决策模型生成失败:' + error)
        })
    },
    async GetDataList() {
      this.$axios
        .get('http://localhost/api/tree/getDataList', {
          headers: {
            token: sessionStorage.getItem('token'),
          },
        })
        .then((response) => {
          console.log(response.data)
          if (response.data.code === 200) {
            const fileNames = response.data.data
            this.datasetList = fileNames.map((item, index) => ({
              num: index + 1,
              name: item.name,
            }))
          } else {
            console.error('获取文件列表失败', response.data.msg)
            this.$message.error('获取文件列表失败：' + response.data.msg)
          }
        })
        .catch((error) => {
          console.error('获取文件列表失败', error)
          this.$message.error('获取文件列表失败:' + error)
        })
    },
    renderContent(h, { node }) {
      // 计算节点深度
      let depth = 0
      let parent = node.parent
      while (parent) {
        depth++
        parent = parent.parent
      }

      // 根据深度设置背景色和标志符
      let color = ''
      let prefix = ''
      switch (depth) {
        case 0:
          color = 'lightblue'
          prefix = '🌳'
          break
        case 1:
          color = 'lightgreen'
          prefix = '🌿'
          break
        case 2:
          color = 'lightcoral'
          prefix = '🍂'
          break
        // 更多深度可以继续添加case
        default:
          color = 'black'
          prefix = '🌱'
      }

      return h(
        'div',
        {
          style: {
            color: color,
            padding: '5px',
            borderRadius: '5px',
          },
        },
        `${prefix} ${node.label}`
      )
    },
    selectDataset(dataset) {
      // 检查是否已有选中的数据集
      if (this.selectedDataset && this.selectedDataset === dataset) {
        // 如果点击的是已选中的数据集，则取消选中
        this.selectedDataset = null
      } else {
        // 如果点击的是不同的数据集，或之前没有选中的数据集，将其设置为选中状态
        this.selectedDataset = dataset
      }
      // this.selectedDataset = dataset;
    },
    async deleteDecisionTree() {
      this.$axios
        .delete(
          'http://localhost/api/tree/deleteTree?treeId=' + this.decisionTreeId,
          {
            headers: {
              token: sessionStorage.getItem('token'),
            },
          }
        )
        .then((response) => {
          console.log(response.data)
          if (response.data.data) {
            this.$message.success('文件删除成功')
            // 从tableData 移除已删除的文件
            this.tableData = this.tableData.filter(
              (data) => !this.decisionTreeId.includes(data.id)
            )
          } else {
            this.$message.error('删除失败：' + response.data.msg)
          }
        })
        .catch((error) => {
          console.error('删除文件失败', error)
          this.$message.error('删除文件失败:' + error)
        })
    },
    async generateDecisionTree() {
      // 生成决策树的逻辑，包括 ID，选择的数据集，输入的指令
      // 构建 URL 查询参数
      if(!this.decisionTreeId) {
        this.$message.error("请填写决策树模型！")
      }
      if(!this.selectedDataset.name){
        this.$message.error("请选择数据集！")
      }
      if(!this.numHosts){
        this.$message.error("请输入主机数量！")
      }
      let isLegal = this.generateCommand()
      if(isLegal&&this.decisionTreeId&& this.numHosts&&this.selectedDataset.name){//&&this.selectedDataset.name
        const params = new URLSearchParams({
        treeId: this.decisionTreeId,
        code: this.command,
        fileName: this.selectedDataset.name,
      }).toString()
      console.log(
        '生成决策模型',
        this.decisionTreeId,
        this.selectedDataset.name,
        this.command
      )
      this.command = ''
      await this.$axios
        .get(`http://localhost/api/tree/generateTree?${params}`, {
          headers: {
            token: sessionStorage.getItem('token'),
          },
        })
        .then((response) => {
          console.log(response.data)
          if (response.data.data) {
            this.$message.success('等待决策模型生成')
            this.getTreeData(this.decisionTreeId)
          } else {
            this.$message.error('决策模型生成失败：' + response.data.msg)
          }
        })
        .catch((error) => {
          console.error('决策模型生成失败', error)
          this.$message.error('决策模型生成失败:' + error)
        })
      }
    },
    applicationDecisionTree() {
      if (this.decisionTreeId == null) {
        this.$message.error('无决策模型名称')
      } else {
        console.log('okok' + this.decisionTreeId)
        this.$router.push({
          path: '/TreeApplication',
          query: {
            decisionTreeIdTobeUsed: this.decisionTreeId,
          },
        })
      }
    },
  },
  mounted() {
    this.decisionTreeId = this.$route.query.decisionTreeName
    this.selectedDataset = {
      name: this.$route.query.dataSet,
    }
    console.log(this.$route.query.dataSet + 'asdhgjfla;ksjglk;jasgl;ka')
    this.getTreeData(this.decisionTreeId)
    this.$nextTick(() => {
      this.GetDataList()
      const matchingDataset = this.datasetList.find(
        (item) => item.name === this.$route.query.dataSet
      )
      if (matchingDataset) {
        this.selectDataset(matchingDataset)
      }
    })
  },
}
</script>

<style scoped>
.container {
  display: flex;
  height: 84vh;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* 添加阴影效果 */
}

.left-panel,
.right-panel {
  padding: 20px;
  overflow: auto;
  border-radius: 8px;
}
.command-input{
  overflow: auto;
}

.left-panel {
  width: 70%;
  background-color: white;
}

.right-panel {
  display: flex;
  flex-direction: column;
  width: 30%;
  gap: 20px;
}

.panel {
  background: #ffffff;
  border: 1px solid #ebebeb;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  padding: 15px;
  margin-bottom: 5px;
}

.el-input__inner {
  border: none;
  border-bottom: 2px solid #dcdfe6;
  box-shadow: none;
}

.el-input__inner:focus {
  border-bottom-color: #409eff;
  box-shadow: none;
}

.data-list {
  overflow-y: auto;
  overflow-x: auto;
  max-height: 100px;
  white-space: nowrap; /* 防止自动换行 */
}

.data-list ul {
  list-style-type: none;
  padding: 0;
}

.list-item {
  cursor: pointer;
  padding: 10px;
  border-radius: 4px;
  transition: background-color 0.3s, color 0.3s;
  white-space: nowrap;
}

.list-item:hover {
  background-color: #e9ecef;
}

.list-item.selected {
  background-color: #409eff;
  color: white;
  border-color: #409eff;
}

/* Button Styling */
.btn-application,
.btn-delete,
.btn-generate {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
  font-size: 16px;
  font-weight: bold;
  width: 30%;
  margin-bottom: 5px;
  margin-left: 5px;
  background-color: #409eff;
  color: white;
}

.btn-application:hover,
.btn-delete:hover,
.btn-generate:hover {
  background-color: #367bdd;
}

.panel,
.btn-application,
.btn-delete,
.btn-generate,
.el-input__inner {
  transition: all 0.3s ease;
}
</style>
